package edu.tongji.gridding.query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.ansj.util.recognition.NatureRecognition;

import com.tongji.gridding.hbase.HBaseDao;

import edu.tongji.gridding.database.DocumentIndexDao;
import edu.tongji.gridding.database.TitleIndexDao;
import edu.tongji.gridding.datamodel.Response;
import edu.tongji.gridding.datamodel.Result;
import edu.tongji.gridding.thread.QueryManager;
import edu.tongji.gridding.utils.CommonUtils;
import edu.tongji.gridding.utils.StringUtils;


public class Query {
	
	private HBaseDao dao;
	private DocumentIndexDao documentIndexDao;
	private TitleIndexDao titleIndexDao;
	private QueryManager queryManager;
	
	
	public Query(HBaseDao dao) {
		this.dao = dao;
		init();
	}
	
	private void init() {
		documentIndexDao = new DocumentIndexDao(dao);
		titleIndexDao = new TitleIndexDao(dao);
		queryManager = new QueryManager(documentIndexDao, titleIndexDao);
	}
	
//	public List<String> orQuery(String[] keywords, int cnt) {
//		List<String> dQuery = new ArrayList<String>();
//		List<String> tQuery = new ArrayList<String>();
//		
//		for(String keyword : keywords) {
//			dQuery.addAll(documentIndexDao.queryDocument(keyword, cnt));
//			tQuery.addAll(titleIndexDao.queryTitle(keyword, cnt));
//		}
//		tQuery.addAll(dQuery);
//		
//		if(tQuery == null || tQuery.size() == 0) {
//			return null;
//		}
//		return CommonUtils.getSubList(tQuery, cnt);
//	}
	
	public List<String> orQuery(String[] keywords, int cnt) {
		List<String> fps = new ArrayList<String>();
		try {
			Response response = queryManager.queryDocAndTitle(keywords);
			List<Result> dResults = response.getDocQueryResults();
			List<Result> tResults = response.getTitleQueryResults();
			for(Result r : dResults) {
				fps.addAll(r.getReulsts());
			}
			for(Result r : tResults) {
				fps.addAll(r.getReulsts());
			}
		} catch (Exception e) {
			System.err.println(e);
		}
		
		return CommonUtils.getSubList(fps, cnt);
	}
	
//	public List<String> andQuery(String[] keywords, int cnt) {
//		Map<String, String> dHash = new HashMap<String, String>();
//		Map<String, String> tHash = new HashMap<String, String>();
//		
//		for (String keyword : keywords) {
//			for(String fp : documentIndexDao.queryDocument(keyword, -1)) {
//				add2HashMap(dHash, fp, keyword);
//			}
//			for(String fp : titleIndexDao.queryTitle(keyword, -1)) {
//				add2HashMap(tHash, fp, keyword);
//			}
//		}
//		List<String> dQuery = filterHashMap(dHash, StringUtils.array2String(keywords));
//		List<String> tQuery = filterHashMap(tHash, StringUtils.array2String(keywords));
//		tQuery.addAll(dQuery);
//
//		return CommonUtils.getSubList(tQuery, cnt);
//	}
	
	public List<String> andQuery(String[] keywords, int cnt) {
		Map<String, String> dHash = new HashMap<String, String>();
		Map<String, String> tHash = new HashMap<String, String>();
		
		List<String> results = new ArrayList<String>();
		
		try {
			Response response = queryManager.queryDocAndTitle(keywords);
			List<Result> dResults = response.getDocQueryResults();
			List<Result> tResults = response.getTitleQueryResults();
			
			for(Result r : dResults) {
				for(String fp : r.getReulsts()) {
					add2HashMap(dHash, fp, r.getKeyword());
				}
			}
			for(Result r : tResults) {
				for(String fp : r.getReulsts()) {
					add2HashMap(tHash, fp, r.getKeyword());
				}
			}
			List<String> dQuery = filterHashMap(dHash, getAndFlag(dResults));
			List<String> tQuery = filterHashMap(tHash, getAndFlag(tResults));
			
			results.addAll(tQuery);
			results.addAll(dQuery);
		} catch (Exception e) {
			System.err.println(e);
		}
		return CommonUtils.getSubList(results, cnt);
	}
	
	
	
	public List<String> query(String keyword, int cnt) {
		List<String> dQuery = documentIndexDao.queryDocument(keyword, -1);
		List<String> tQuery = titleIndexDao.queryTitle(keyword, -1);
		tQuery.addAll(dQuery);
		
		if(tQuery == null || tQuery.size() == 0) {
			return null;
		}
		return CommonUtils.getSubList(tQuery, cnt);
	}

	private List<String> filterHashMap(Map<String, String> map, String filter) {
		List<String> result = new ArrayList<String>();
		
		Set<Map.Entry<String, String>> set = map.entrySet();
		for(Iterator<Map.Entry<String, String>> iterator = set.iterator(); iterator.hasNext(); ) {
			Map.Entry<String, String> entry = iterator.next();
			
			if(filter.equals(entry.getValue())) {
				result.add(entry.getKey());
			}
		}
		return result;
	}
	
	public static List<String> getLexemeList(String content, int lexemeMinLength){
		content = StringUtils.getNormalString(content);
		
		List<String> lexemeList = new ArrayList<String>();
		List<Term> terms = ToAnalysis.paser(content);
		new NatureRecognition(terms).recognition() ;
		for(Term term : terms) {
			System.out.println(term.getNatrue().natureStr);
			if(isWanted(term) && term.getName().length()>=lexemeMinLength) {
				if(!StringUtils.isBlank(term.getName())) {
					lexemeList.add(term.getName());
				}
			}
		}
		return lexemeList;
	}
	
	private static boolean isWanted(Term term) {
		String regx = "ag|c|e|dg|g|h|k|ng|p|r|q|u.*|y";
		Pattern pattern = Pattern.compile(regx);

		if(term.getNatrue()!=null && term.getNatrue().natureStr!=null
				&& !"null".equals(term.getNatrue().natureStr)) {
			Matcher matcher = pattern.matcher(term.getNatrue().natureStr);
			if(matcher.matches()) {
				return false;
			}
			
			if("en".equals(term.getNatrue().natureStr.toLowerCase())) {
				if(term.getName().length() == 1 || term.getName().length() > 15) {
					return false;
				}
			}
		}
		return true;
	}
	
	private void add2HashMap(Map<String, String> map, String key, String value) {
		if(!map.containsKey(key)) {
			map.put(key, value);
			return;
		}
		value = map.get(key) + "|" + value;
		map.put(key, value);
	}
	
	private String getAndFlag(List<Result> rs) {
		String[] s = new String[rs.size()];
		for(int i = 0; i < rs.size(); ++ i) {
			s[i] = rs.get(i).getKeyword();
		}
		return StringUtils.array2String(s);
	}
	
	public void release() {
		queryManager.release();
	}
}


